﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.Text;

namespace ETRoboConTrackingSystemServer
{
    // NOTE: You can use the "Rename" command on the "Refactor" menu to change the interface name "IETRoboConRaceMgmt" in both code and config file together.
    [ServiceContract]
    public interface IETRoboConRaceMgmt
    {
        [OperationContract]
        bool GetContestInfo(out ContestInfo[] infos);

        [OperationContract]
        bool GetAreaInfo(int contestid, out AreaInfo[] infos);

        [OperationContract]
        bool GetGameInfo(int contestId, out GameInfo[] infos);

        [OperationContract]
        bool GetBonusSpecInfo(int gameId, CourseName course, out BonusSpecInfo[] infos);

        /// <summary>
        /// gameIdから現在のRoundを取り出す。
        /// </summary>
        /// <param name="gameId">現在のGameId</param>
        /// <param name="roundNo">指定されたGameIdのカレントのラウンドの番号</param>
        /// <param name="roundId">指定されたGameIdのカレントのRoundのId</param>
        /// <returns>カレントのラウンドが存在すればtrueを返す。</returns>
        [OperationContract]
        bool GetCurrentRound(int gameId, out int roundNo, out int roundId);

        [OperationContract]
        bool GetTurnInfo(int currentRoundId, out int turnNo, out int turnId, out int inCourseRunnerId, out int outCourseRunnerId);

        [OperationContract]
        bool StartRound(int gameId, int roundNo, out int roundId);

        [OperationContract]
        bool ContinueRound(int gameId, out int roundId);

        [OperationContract]
        bool EndRound(int currentRoundId);

        [OperationContract]
        bool RollbackTurn(int currentRoundId);

        [OperationContract]
        bool NotifyRaceResult(int turnId, int currentRunnerId, RunnerStatus status, int runTime, int[] bonusClearResult, out int point);

        [OperationContract]
        bool NotifyObstructed(int turnId, int currentRunnerId, bool retryNow);

        [OperationContract]
        bool GetTeamInfoByEntryTeam(int entryTeamId, out TeamInfo teamInfo);

        [OperationContract]
        bool GetEntryTeamInfo(int gameId, out TeamInfo[] temaInfos);

        [OperationContract]
        bool GetGameSpecInfo(out GameSpecInfo[] gameSpecInfos);

        [OperationContract]
        bool GetRaceOrder(int gameId, int roundNo, out TurnInfo[] turnInfos);

        [OperationContract]
        bool GetTeamRaceResult(int turnID, int entryTeamId, out RunnerStatus status, out int? runTime, out int? runPoint, out string[] bonusResults);

        [OperationContract]
        bool UpdateTeamRaceResult(int turnID, int entryTeamId, RunnerStatus status, int? runTime, string[] bonusResults,  out int? runPoint);

        [OperationContract]
        bool UpdateEntryTeamResultInfo(int entryTeamId, int? modelPoint, int? rank);

        [OperationContract]
        bool UpdateEntryTeamModelPoint(int entryTeamId, int modelPoint);

        [OperationContract]
        bool GetEntryTeamResultInfos(int gameId, out EntryTeamResultInfo[] results, bool doCalc);

        [OperationContract]
        bool RegistContest(string name, string memo, int year, out int contestId);

        [OperationContract]
        bool RegistNewGame(int areaId, int gameSpecId, string gameName, out int gameId);

        [OperationContract]
        bool ClearGameRound(int gameId);

        [OperationContract]
        bool RegistTeam(int contestId, string areaName, string teamName, string categoryName, string Id, long regId, out int teamId);

        [OperationContract]
        bool RegistEntryTeam(int gameId, int teamId, int bib, bool isExibition, out int entryTeamId);

        [OperationContract]
        bool RegistRound(int gameId, int roundNo, out int roundId);

        [OperationContract]
        bool RegistRound2AllTurnsByAuto(int gameId, int round1Id, out int round2Id);

        [OperationContract]
        bool RegistTurn(int roundId, int inCourseRunnerId, int outCourseRunnerId, out int turnId);

        [OperationContract]
        bool FixTurnRunner(int gameId);

        [OperationContract]
        bool ClearEntryTeamModelPoint(int gameId);

        [OperationContract]
        bool ClearGameInfo(int gameId);

        [OperationContract]
        bool ClearGameSpecInfo(string gameSpecName);

        [OperationContract]
        GameSpecInfo FindGameSpec(string gameSpecName);

        [OperationContract]
        bool RegistGameSpec(string gameSpecName, string Memo, out int gameSpecId);

        [OperationContract]
        bool ClearBonusSpecs(string gameSpecName, CourseName courseName);

        [OperationContract]
        bool UpdaetGameSpecInfo(int gameSpecId, string name, string memo);

        [OperationContract]
        bool AppendBonusSpec(int gameSpecId, CourseName courseName, string name, string shortName, string specification, int point, out int clearOrder, out int bonusSpecId);

        [OperationContract]
        bool GetGameCourseBonusSpecInfo(int gameSpecId, CourseName courseName, out BonusSpecInfo[] infos);

        [OperationContract]
        bool GetContestById(int contestId, out int year, out string name, out string memo);

        [OperationContract]
        bool LoadGameSpec(string specName, string definition);

        [OperationContract]
        bool LoadTeamInfo(string contestName, string definition);

        [OperationContract]
        bool GetTurnInfoOfTeam(int gameId, string teamExId, long teamRegId, int roundNo, out int entryTeamId, out int turnNo, out CourseName course);

        [OperationContract]
        bool LoadContestInfo(string definition);

        /// <summary>
        /// 指定のラウンドの未開始のターンで一番早いターンを指定ターンだけ後にずらす
        /// </summary>
        /// <param name="roundNo">移動したいRoundのId</param>
        /// <param name="isLast">trueの場合最後に移動。falseの場合次の次に移動</param>
        /// <returns>引数が妥当でない場合（指定したGameがない、指定したRoundがない）はfalseを、妥当な場合はtrueを返す</returns>
        [OperationContract]
        bool MoveCurrentTurnToFollow(int roundId, bool isLast);

        [OperationContract]
        bool GetTeamTotalResults(int gameId, out TeamTotalResult[] results);
    }

    [DataContract]
    public class ContestInfo
    {
        [DataMember]
        public int ContestId { get; set; }
        [DataMember]
        public string Name { get; set; }
    }

    [DataContract]
    public class AreaInfo
    {
        [DataMember]
        public int AreaId { get; set; }
        [DataMember]
        public string Name { get; set; }
    }

    [DataContract]
    public class GameInfo
    {
        [DataMember]
        public int GameId { get; set; }

        [DataMember]
        public string Name { get; set; }

        [DataMember]
        public int GameSpecId { get; set; }

        [DataMember]
        /// <summary>
        /// このプロパティは、本来、Teamの情報に付くべきもの
        /// チャンピオンシップ時は見直し必要
        /// ただし、現状、登録するインタフェースがないので
        /// ゲーム情報に紐付る
        /// </summary>
        public string AreaName { get; set; }
    }

    [DataContract]
    public class TeamInfo
    {
        [DataMember]
        public int TeamId { get; set; }

        [DataMember]
        public int EntryTeamId { get; set; }

        [DataMember]
        public int Bib { get; set; }

        [DataMember]
        public string Name { get; set; }

        [DataMember]
        public bool Exhibition { get; set; }

        [DataMember]
        public string Id { get; set; }

        [DataMember]
        public long RegId { get; set; }
    }

    [DataContract]
    public class EntryTeamResultInfo
    {
        [DataMember]
        public Int64 TeamRegId { get; set; }

        [DataMember]
        public int TeamId { get; set; }

        [DataMember]
        public int EntryTeamId { get; set; }

        [DataMember]
        public int Bib { get; set; }

        [DataMember]
        public string TeamName { get; set; }

        [DataMember]
        public int? ModelPoint { get; set; }
 
        [DataMember]
        public int? TotalRunPoint { get; set; }

        [DataMember]
        public double? TotalPoint { get; set; }

        [DataMember]
        public int? Rank { get; set; }
    }

    [DataContract]
    public class GameSpecInfo
    {
        [DataMember]
        public int GameSpecId { get; set; }

        [DataMember]
        public string Name { get; set; }

        [DataMember]
        public string Memo { get; set; }
    }

    [DataContract]
    public class TurnInfo
    {
        [DataMember]
        public int TurnId { get; set; }
        [DataMember]
        public int No { get; set; }
        [DataMember]
        public int InCourseRunnerId { get; set; }
        [DataMember]
        public int OutCourseRunnerId { get; set; }
    }

    [Serializable]
    public enum CourseName
    {
        IN,
        OUT
    }

    [DataContract]
    public class BonusSpecInfo
    {
        [DataMember]
        public int BonusSpecId { get; set; }
        [DataMember]
        public string Name { get; set; }
        [DataMember]
        public string ShortName { get; set; }
        [DataMember]
        public string Specification { get; set; }
        [DataMember]
        public int Point { get; set; }
        [DataMember]
        public int ClearOrder { get; set; }
        [DataMember]
        public int GameCourseSpecId { get; set; }
    }

    [DataContract]
    public class TeamTotalResult
    {
        [DataMember]
        public int TeamId { get; set; }
        [DataMember]
        public int Bib { get; set; }
        [DataMember]
        public string Name { get; set; }
        [DataMember]
        public double? NormalizedResultPoints { get; set; }
        [DataMember]
        public double? NormalizedModelPoint { get; set; }
        [DataMember]
        public int? Rank { get; set; }
        [DataMember]
        public string InCourseResult { get; set; }
        [DataMember]
        public string OutCourseResult { get; set; }
    }

    [Serializable]
    public enum RunnerStatus
    {
        UNKNOWN,
        READY,
        COMPLETED,
        RETIRED,
        OBSTRUCTED,
        DECLINED,
    }

}
